using System.Linq.Expressions;
using System.Threading;
using Ioc.Kernel.LifeStyles;
using MbUnit.Framework;

namespace Ioc.Kernel.Test.LifeStyleTests.ThreadTestStrategy
{
    public interface IThreadProcessStrategy
    {
        void Process(ThreadLifeStyleStrategy lifeStyles);
    }

    public class SetExpressionTest_ForceSettingNewExistingInstance : IThreadProcessStrategy
    {
        public void Process(ThreadLifeStyleStrategy lifeStyles)
        {
            lifeStyles.SetExpression(Expression.New(typeof(FakeClass)));
            Thread.SetData(Thread.GetNamedDataSlot("IsRegistered"), null);
            lifeStyles.SetExpression(Expression.New(typeof(FakeClass2)));
            var expression = lifeStyles.GetExpression(typeof(FakeClass2));
            Assert.AreEqual(typeof(FakeClass2).FullName, expression.Type.FullName, "Expression should be of type 'FakeClass2'");
        }
    }

    public class SetExpressionTest_SettingExistingInstance : IThreadProcessStrategy
    {
        public void Process(ThreadLifeStyleStrategy lifeStyles)
        {
            lifeStyles.SetExpression(Expression.New(typeof (FakeClass)));
            var expression1 = lifeStyles.GetExpression(typeof(FakeClass));
            lifeStyles.SetExpression(Expression.New(typeof(FakeClass)));
            var expression2 = lifeStyles.GetExpression(typeof (FakeClass));

            Assert.AreEqual(expression1.Type.FullName, expression2.Type.FullName);
        }
    }

    public class SetExpressionTest_NewInstance : IThreadProcessStrategy
    {
        public void Process(ThreadLifeStyleStrategy lifeStyles)
        {
            lifeStyles.SetExpression(Expression.New(typeof(FakeClass)));
            var expression = lifeStyles.GetExpression(typeof(FakeClass));
            Assert.AreEqual(typeof(FakeClass).FullName, expression.Type.FullName, "Expression should be of type 'FakeClass'");
        }
    }

    public class GetExpressionTest_WithNoExpressionPassed : IThreadProcessStrategy
    {
        public void Process(ThreadLifeStyleStrategy lifeStyles)
        {
            var expression = lifeStyles.GetExpression(typeof (FakeClass));
            Assert.IsNull(expression, "Expression should contains a null value");
        }
    }

    public class MustInstanciateTest_WithThreadsSonsCallingMoreThanOneTimes : IThreadProcessStrategy
    {
        public void Process(ThreadLifeStyleStrategy lifeStyles)
        {
            Assert.IsTrue(lifeStyles.MustInstanciate(), "Should be true if no expression is registered");

            lifeStyles.SetExpression(Expression.New(typeof(FakeClass)));
            Assert.IsFalse(lifeStyles.MustInstanciate(), "Should be false cause a component is registered yet");
        }
    }

    public class MustInstanciateTest_WithThreadsSons : IThreadProcessStrategy
    {
        public void Process(ThreadLifeStyleStrategy lifeStyles)
        {
            Assert.IsTrue(lifeStyles.MustInstanciate(), "Should be true if no expression is registered");
        }
    }
}